package 力扣;
//判断一个 9x9 的数独是否有效。只需要根据以下规则，验证已经填入的数字是否有效即可。
//
//    数字 1-9 在每一行只能出现一次。
//    数字 1-9 在每一列只能出现一次。
//    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

public class 有效的数独 {
    public static void main(String[] args) {

    }

    public static boolean isValidSudoku(char[][] board) {
        // 1. 判断每一行是否有重复元素：rows[i][num] > 1? false: true
        // 2. 判断每一列是否有重复元素：cols[j][num] > 1? false: true
        // 3. 判断每一个子数独是否有重复元素：boxs[(i/3)*3 + j/3][num] > 1? false: true
        // 直接把1.2.3加起来如果大于3，即不是有效数独
        // 其他：len是一个固定值9。

        // 记录某行，某位数字是否已经被摆放
        int[][] rows = new int[9][10];
        // 记录某列，某位数字是否已经被摆放
        int[][] cols = new int[9][10];
        // 记录某 3x3 宫格内，某位数字是否已经被摆放
        int[][] boxs = new int[9][10];

        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if (board[i][j] == '.')
                    continue;
                //将字符转换为数字
                int num = board[i][j] - '0';
                rows[i][num]++;
                cols[j][num]++;
                // i是行标，j是列标。行标决定一组block的起始位置（因为block为3行，所以除3取整得到组号，
                // 又因为每组block为3个，所以需要乘3），列标再细分出是哪个block（因为block是3列，所以除3取整）
                // 子数独id的计算：(row / 3) * 3 + col / 3
                boxs[(i / 3) * 3 + j / 3][num]++;
                //>3 说明有重复数字
                if (rows[i][num] + cols[j][num] + boxs[(i / 3) * 3 + j / 3][num] > 3) {
                    return false;
                }
            }
        }
        return true;
    }
}
